﻿using System;
using System.Web.Mvc;

using mvcForum.Core;
using mvcForum.Core.Abstractions.Interfaces;
using mvcForum.Core.Specifications;
using mvcForum.Web.Interfaces;
using mvcForum.Core.Interfaces.Data;
using mvcForum.Core.Interfaces.Services;

namespace mvcForum.Web.Extensions {

	public static class TopicExtensions {

		/// <summary>
		/// Method for tracking the user's visit to a given topic.
		/// </summary>
		/// <param name="forum">The topic that has been visited.</param>
		public static void Track(this Topic topic) {
			// Let's get the UserProvider.
			IWebUserProvider userProvider = DependencyResolver.Current.GetService<IWebUserProvider>();
			// Are we dealing with an authenticated user?
			if (userProvider.Authenticated) {
				try {
					IContext context = DependencyResolver.Current.GetService<IContext>();
					// Let's get the user repo.
					IRepository<ForumUser> userRepository = context.GetRepository<ForumUser>();
					// Let's get the forumtrack repo.
					IRepository<TopicTrack> ttRepository = context.GetRepository<TopicTrack>();
					// Get the authenticated user.
					ForumUser user = userProvider.ActiveUser;
					//ForumUser user = userRepository.Read(userProvider.CurrentUserId);
					// Did we get an user?
					if (user != null) {
						// Let's track the user's visit to the given forum.
						TopicTrack tt = ttRepository.ReadOne(new TopicTrackSpecifications.SpecificTopicAndUser(topic, user));
						// Did we get a topic track?
						if (tt == null) {
							// No, let's create one then!
							tt = new TopicTrack(topic, user);
							ttRepository.Create(tt);
						}
						// Update the Forumtrack instance (LastViewed).
						tt.Viewed();
						context.SaveChanges();
					}
				}
				catch (Exception ex) {
					// And error occured, let's log it.
					DependencyResolver.Current.GetService<ILogger>().Log(EventType.Error, "Track extension on Forum failed.", ex);
				}
			}
		}

		/// <summary>
		/// Method for tracking the user's visit to a given topic and counting the view.
		/// </summary>
		/// <param name="forum">The topic that has been visited.</param>
		public static void TrackAndView(this Topic topic) {
			// Track it!
			topic.Track();
			// Let's get the UserProvider.
			IWebUserProvider userProvider = DependencyResolver.Current.GetService<IWebUserProvider>();
			// Are we dealing with an authenticated user?
			// TODO: Only track views from authenticated users!?!?!?! setting?!?!?!?
			if (userProvider.Authenticated) {
				topic.Viewed();
				// Update it!
				DependencyResolver.Current.GetService<IContext>().SaveChanges();
			}
		}

		/// <summary>
		/// Method for getting the user's last visit to a given topic.
		/// </summary>
		/// <param name="forum">The topic we need to get the last visisted timestamp for.</param>
		/// <returns>A timestamp indication when the user last visited the given topic.</returns>
		public static DateTimeOffset LastRead(this Topic topic) {
			// Get the UserProvider.
			IWebUserProvider userProvider = DependencyResolver.Current.GetService<IWebUserProvider>();
			// Do we have an authenticated user?
			if (userProvider.Authenticated) {
				try {
					// Yes, lets' get the ForumUser repository.
					IRepository<ForumUser> userRepo = DependencyResolver.Current.GetService<IRepository<ForumUser>>();
					// And the user.
					ForumUser user = userProvider.ActiveUser;
					//ForumUser user = userRepo.Read(userProvider.CurrentUserId);
					if (user != null) {
						// Get the TopicTrack repository.
						IRepository<TopicTrack> ttRepo = DependencyResolver.Current.GetService<IRepository<TopicTrack>>();
						// Get the TopicTrack for the given user and topic.
						TopicTrack tt = ttRepo.ReadOne(new TopicTrackSpecifications.SpecificTopicAndUser(topic, user));
						// If we got one, let's return the LastViewed property, otherwise a timestamp from waaaay back.
						return (tt == null ? DateTimeOffset.MinValue.ToUniversalTime() : tt.LastViewed);
					}
				}
				catch (Exception ex) {
					// Ups, and error occured, let's log it.
					DependencyResolver.Current.GetService<ILogger>().Log(EventType.Error, "LatRead extension on Topic failed.", ex);
				}
			}
			// Not authenticated user, return NOW, we don't track anonymous users!
			return DateTime.UtcNow;
		}

		/// <summary>
		/// Method for finding out whether or not the user is following a given topic.
		/// </summary>
		/// <param name="topic">The given topic.</param>
		/// <returns>True if the user is following the topic, otherwise false.</returns>
		public static Boolean Following(this Topic topic) {
			// Get the UserProvider.
			IWebUserProvider userProvider = DependencyResolver.Current.GetService<IWebUserProvider>();
			// Are we dealing with an authenticated user?
			if (userProvider.Authenticated) {
				// Yes, lets' get the ForumUser repository.
				IRepository<ForumUser> userRepository = DependencyResolver.Current.GetService<IRepository<ForumUser>>();
				// Get the user!
				ForumUser user = userProvider.ActiveUser;
				//ForumUser user = userRepository.Read(userProvider.CurrentUserId);
				// Did we get an user?
				if (user != null) {
					// Yes, let's get the FollowTopic repository.
					IRepository<FollowTopic> ftRepository = DependencyResolver.Current.GetService<IRepository<FollowTopic>>();
					// Get a FollowTopic instance for the user, if we get one, he's following, if not, he isn't.
					return (ftRepository.ReadOne(new FollowTopicSpecifications.SpecificTopicAndUser(topic, user)) != null);
				}
			}
			// Nope, not following this topic, no authenticated user found.
			return false;
		}
	}
}